package com.inspur.edp.web.relycheck.dependencyvalidator;

import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.spi.MetadataElementValidator;
import com.inspur.edp.lcm.metadata.spi.entity.MetadataElement;
import com.inspur.edp.lcm.metadata.spi.entity.ValidateResult;
import com.inspur.edp.web.common.logger.WebLogger;
import com.inspur.edp.web.common.utility.StringUtility;
import com.inspur.edp.web.relycheck.constant.RelyCheckType;
import com.inspur.edp.web.relycheck.constant.ValidateConstants;
import com.inspur.edp.web.relycheck.dependencygenerator.entity.SourceElementEntity;
import com.inspur.edp.web.relycheck.utility.StringConcatUtility;
import com.inspur.edp.web.relycheck.utility.ValidateResultUtility;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 关联的 VoEntity 依赖验证
 *
 * @author noah
 */
public class VoEntityValidator extends AbstractDependencyValidator implements MetadataElementValidator {
    private final RelyCheckType relyCheckType = RelyCheckType.SchemaEntity;

    @Override
    public String getReferenceType() {
        return RelyCheckType.SchemaEntity.getReferenceType();
    }

    @Override
    public ValidateResult validate(MetadataElement sourceMetadataElement, MetadataElement targetMetadataElement,
                                   GspMetadata sourceGspMetadata, GspMetadata targetGspMetadata) {
        if (sourceMetadataElement != null && sourceGspMetadata != null &&
                sourceMetadataElement.getType().equals(relyCheckType.getType()) &&
                targetMetadataElement.getType().equals("VoEntity")) {
            // 比较 SchemaEntity 的名称
            SourceElementEntity schemaEntity = (SourceElementEntity) sourceMetadataElement.getContent();
            GspViewObject gspViewObject = (GspViewObject) targetMetadataElement.getContent();
            String formMetadataName = sourceGspMetadata.getHeader().getName();
            // 1.VO元数据被删除
            if (targetGspMetadata == null) {
                // 说明VO元数据已经不存在 那么需要将对应表单移除
                // 理论上不应该出现此种情况
                return ValidateResultUtility.failureWithError(String.format("表单%1$s关联视图对象不存在" + ValidateConstants.Comma + "该表单将无法正确运行" + ValidateConstants.Comma + "请调整关联视图对象或移除该表单",
                        StringConcatUtility.concatWithNamePrefix(formMetadataName, true)
                ));
            }
            String voMetadataName = targetGspMetadata.getHeader().getName();
            // 2.VO元数据中子表删除
            if (targetMetadataElement.getContent() == null) {
                // 说明删除了对应的对象
                return ValidateResultUtility.failureWithError(String.format("视图对象%1$s删除了子表%2$s" + ValidateConstants.Comma + "请在表单%3$s的实体树中执行更新schema操作",
                        StringConcatUtility.concatWithNamePrefix(voMetadataName, true),
                        StringConcatUtility.concatWithCodePrefix(schemaEntity.getSourceEntity().getCode(), true),
                        StringConcatUtility.concatWithNamePrefix(formMetadataName, true)
                ));
            }
            // 3.VO元数据中子表编号更改
            if (!StringUtility.equals(schemaEntity.getSourceEntity().getCode(), gspViewObject.getCode())) {
                return ValidateResultUtility.failureWithError(String.format("视图对象%1$s更改了%2$s的子表" + ValidateConstants.Comma + "请在表单%3$s的实体树中执行更新schema操作",
                        StringConcatUtility.concatWithNamePrefix(voMetadataName, true),
                        StringConcatUtility.concatWithCodePrefix(gspViewObject.getCode(), true),
                        StringConcatUtility.concatWithNamePrefix(formMetadataName, true)
                ));
            }

            // 判断 schema 中的字段是否全部在vo 存在
            // 字段删除判断放在vo element 校验中
//            AtomicReference<String> schemaEntityFieldCode = new AtomicReference<>("");
//            boolean allSchemaFieldsInVo = schemaEntity.getSourceEntity().getType().getFields().stream().allMatch(t -> {
//                        boolean exists = gspViewObject.getContainElements().stream().anyMatch(m -> m.getCode().equals(t.getCode()));
//                        if (!exists) {
//                            schemaEntityFieldCode.set(t.getCode());
//                        }
//                        return exists;
//                    }
//            );
//            if (!allSchemaFieldsInVo) {
//                return this.failureWithError(String.format("视图对象%1$s删除了字段" + ValidateConstants.Colon + "%2$s" + ValidateConstants.Comma + "请在表单%3$s的实体树中执行更新schema操作",
//                        StringConcatUtility.concatWithNamePrefix(voMetadataName, true),
//                        StringConcatUtility.concatWithCodePrefix(schemaEntityFieldCode.get(), true),
//                        StringConcatUtility.concatWithNamePrefix(formMetadataName, true)
//                ));
//            }

            // 判断vo 中的字段是否全部在 schema 中
            AtomicReference<String> addedVoFieldCode = new AtomicReference<>("");
            AtomicReference<String> addedVoFieldName = new AtomicReference<>("");
            boolean allVoFieldsInSchema = gspViewObject.getContainElements().stream().allMatch(t -> {
                        boolean exists = schemaEntity.getSourceEntity().getType().getFields().stream().anyMatch(m -> m.getCode().equals(t.getCode()));
                        if (!exists) {
                            addedVoFieldCode.set(t.getCode());
                            addedVoFieldName.set(t.getName());
                        }
                        return exists;
                    }
            );

            if (!allVoFieldsInSchema) {
                return ValidateResultUtility.failureWithWarning(String.format("视图对象%1$s新增了字段" + ValidateConstants.Colon + "%2$s" + ValidateConstants.Comma + "若要在表单使用该字段" + ValidateConstants.Comma + "请在表单%3$s的实体树中执行更新schema操作",
                        StringConcatUtility.concatWithNamePrefix(voMetadataName, true),
                        StringConcatUtility.concatWithCodePrefix(addedVoFieldCode.get(), true),
                        StringConcatUtility.concatWithNamePrefix(formMetadataName, true)
                ));
            }

        } else {
            WebLogger.Instance.info("SchemaEntity 校验，不是有效的 SchemaEntity 类型");
        }
        return ValidateResultUtility.success();
    }
}
